#pragma once
#include "DXContext.h"
#include "enums.h"
#include "primitives.h"

namespace DXBase
{
	namespace DWrite
	{
		ref class TextFormat;
		ref class TextLayout;
		ref class GlyphRun;
	}
	namespace D2D
	{
		interface class IBrush;
		interface class IGeometry;
		ref class StrokeStyle;
		ref class Bitmap;

		[Windows::Foundation::Metadata::WebHostHidden]
		public ref class D2DGraphics sealed
		{
		public:
			D2DGraphics(DXBase::DXContext^ ctxt);
			property DXContext^ Context { DXContext^ get() { return mContext; } }

			void Clear(Windows::UI::Color bg);
			void Flush();

			property float3x2 Transform
			{
				float3x2 get();
				void set(float3x2 value);
			}
			property UnitMode UnitMode
			{
				D2D::UnitMode get();
				void set(D2D::UnitMode value);
			}

			void DrawBitmap(Bitmap^ bmp, float opacity, INTERPOLATION_MODE im) { DrawBitmap(bmp, nullptr, opacity, im, nullptr, nullptr); }
			void DrawBitmap(Bitmap^ bmp, Windows::Foundation::Rect rect, float opacity, INTERPOLATION_MODE im) { DrawBitmap(bmp, &rect, opacity, im, nullptr, nullptr); }
			void DrawBitmap(Bitmap^ bmp, Windows::Foundation::Rect rect, float opacity, INTERPOLATION_MODE im, Windows::Foundation::Rect srcRect) { DrawBitmap(bmp, &rect, opacity, im, &srcRect, nullptr); }
			void DrawBitmap(Bitmap^ bmp, Windows::Foundation::Rect rect, float opacity, INTERPOLATION_MODE im, Windows::Foundation::Rect srcRect, float4x4 perspective) { DrawBitmap(bmp, &rect, opacity, im, &srcRect, &perspective); }
		private:
			void DrawBitmap(Bitmap^ bmp, Windows::Foundation::Rect* rect, float opacity, INTERPOLATION_MODE im, Windows::Foundation::Rect* srcRect, float4x4* perspective);
		public:

			void DrawLine(float2 p1, float2 p2, IBrush^ brush) { DrawLine(p1, p2, brush, 1, nullptr); }
			void DrawLine(float2 p1, float2 p2, IBrush^ brush, float width, StrokeStyle^ stroke);

			void DrawRectangle(Windows::Foundation::Rect rect, IBrush^ brush) { DrawRectangle(rect, brush, 1, nullptr); }
			void DrawRectangle(Windows::Foundation::Rect rect, IBrush^ brush, float strokeWidth, StrokeStyle^ stroke);
			void FillRectangle(Windows::Foundation::Rect rect, IBrush^ brush);

			void DrawEllipse(Windows::Foundation::Rect rect, IBrush^ brush) { DrawEllipse(rect, brush, 1, nullptr); }
			void DrawEllipse(Windows::Foundation::Rect rect, IBrush^ brush, float strokeWidth, StrokeStyle^ stroke);
			void FillEllipse(Windows::Foundation::Rect rect, IBrush^ brush);

			void DrawRoundedRect(Windows::Foundation::Rect rect, float radiusX, float radiusY, IBrush^ brush) { DrawRoundedRect(rect, radiusX, radiusY, brush, 1, nullptr); }
			void DrawRoundedRect(Windows::Foundation::Rect rect, float radiusX, float radiusY, IBrush^ brush, float strokeWidth, StrokeStyle^ stroke);
			void FillRoundedRect(Windows::Foundation::Rect rect, float radiusX, float radiusY, IBrush^ brush);

			void DrawGeometry(IGeometry^ geom, IBrush^ brush) { DrawGeometry(geom, brush, 1, nullptr); }
			void DrawGeometry(IGeometry^ geom, IBrush^ brush, float strokeWidth, StrokeStyle^ stroke);
			void FillGeometry(IGeometry^ geom, IBrush^ brush) { FillGeometry(geom, brush, nullptr); }
			void FillGeometry(IGeometry^ geom, IBrush^ brush, IBrush^ opacityBrush);

			void DrawText(Platform::String^ string, DWrite::TextFormat^ fmt, Windows::Foundation::Rect layoutRect, IBrush^ defaultForegroundBrush) { DrawText(string, fmt, layoutRect, defaultForegroundBrush, DRAW_TEXT_OPTIONS::NONE, DWrite::MEASURING_MODE::NATURAL); }
			void DrawText(Platform::String^ string, DWrite::TextFormat^ fmt, Windows::Foundation::Rect layoutRect, IBrush^ defaultForegroundBrush, DRAW_TEXT_OPTIONS options, DWrite::MEASURING_MODE measuringMode);

			void DrawTextLayout(float2 p1, DWrite::TextLayout^ textLayout, IBrush^ foreground) { DrawTextLayout(p1, textLayout, foreground, DRAW_TEXT_OPTIONS::NONE); }
			void DrawTextLayout(float2 p1, DWrite::TextLayout^ textLayout, IBrush^ foreground, DRAW_TEXT_OPTIONS options);

			void DrawGlyphRun(float2 baseLineOrigin, DWrite::GlyphRun^ glyphRun, IBrush ^foreground) { DrawGlyphRun(baseLineOrigin, glyphRun, foreground, DWrite::MEASURING_MODE::NATURAL); }
			void DrawGlyphRun(float2 baseLineOrigin, DWrite::GlyphRun^ glyphRun, IBrush ^foreground, DWrite::MEASURING_MODE measuringMode);

		private:
			DXContext^ mContext;
		};
	}
}